package modelo.bd.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import modelo.bd.ConexionPool;
import modelo.bd.excepcion.DAOException;
import modelo.dominio.Evento;
import modelo.servicio.Pasos;

public class EventoDAO {

    private String query;

    public void add(Evento entity, String usuario) throws DAOException {
        Connection conexion = null;
        PreparedStatement sentencia = null;
        PreparedStatement invalidaFlujo = null;
        try {
            query = ("INSERT INTO sil_eventos_flujo \n"
                    + "(evfl_fluj_clave, evfl_pafl_origen, evfl_clave, evfl_descripcion, evfl_desc_corta, \n"
                    + "evfl_requiere_causa, evfl_tipo_causa, evfl_pafl_flujo, "
                    + "evfl_pafl_monto, evfl_tipo_aprobacion, evfl_numero_aprobadores, "
                    + "evfl_valida_forzosos, evfl_usuario_creo, evfl_fecha_creo) \n"
                    + "VALUES('" + entity.getOrigen().getFlujo().getClave().replace("'", "''")
                    + "', '" + entity.getOrigen().getClave().replace("'", "''") + "', '"
                    + entity.getClave() + "', '" + entity.getDescripcion() + "', '"
                    + entity.getDescripcionCorta() + "', '" + (entity.isCausable() ? "S" : "N") + "', '"
                    + entity.getTipoCausa() + "', '"
                    + entity.getSiguiente().getClave().replace("'", "''")
                    + "', '" + (entity.getSiguienteMonto() != null
                    ? entity.getSiguienteMonto().getClave().replace("'", "''")
                    : "") + "', '"
                    + entity.getTipoAprobacion() + "', "
                    + entity.getAprobadores() + ", '" + (entity.isValidaForzosos() ? "S" : "N")
                    + "', '" + usuario + "', SYSDATE)");
            conexion = ConexionPool.getInstancia().getConexion();
            sentencia = conexion.prepareStatement(query);
            sentencia.executeUpdate();
            invalidaFlujo = conexion.prepareStatement(
                    invalidarFlujo(entity.getOrigen().getFlujo().getClave().replace("'", "''"),
                    usuario));
            invalidaFlujo.executeUpdate();
        } catch (SQLException ex) {
            throw new DAOException("Error EVDA-SQL " + ex.getMessage());
        } finally {
            try {
                if (sentencia != null) {
                    sentencia.close();
                }
                if (invalidaFlujo != null) {
                    invalidaFlujo.close();
                }
                if (conexion != null) {
                    conexion.close();
                }
            } catch (SQLException ex) {
                throw new DAOException("Error EVDA-SQL " + ex.getMessage());
            }
        }
    }

    public void deleteWhere(String condition) throws DAOException {
        Connection conexion = null;
        PreparedStatement sentencia = null;
        try {
            query = "DELETE sil_eventos_flujo \n"
                    + "WHERE  " + condition;
            conexion = ConexionPool.getInstancia().getConexion();
            sentencia = conexion.prepareStatement(query);
            sentencia.executeUpdate();
        } catch (SQLException ex) {
            throw new DAOException("Error EVDD-SQL " + ex.getMessage());
        } finally {
            try {
                if (sentencia != null) {
                    sentencia.close();
                }
                if (conexion != null) {
                    conexion.close();
                }
            } catch (SQLException ex) {
                throw new DAOException("Error EVDD-SQL " + ex.getMessage());
            }
        }
    }

    public void update(Evento entity, String usuario) throws DAOException {
        Connection conexion = null;
        PreparedStatement sentencia = null;
        PreparedStatement invalidaFlujo = null;
        try {
            query = "UPDATE sil_eventos_flujo \n"
                    + "SET    evfl_descripcion    = '" + entity.getDescripcion() + "', \n"
                    + "       evfl_desc_corta     = '" + entity.getDescripcionCorta() + "', \n"
                    + "       evfl_requiere_causa = '" + (entity.isCausable() ? "S" : "N") + "', \n"
                    + "       evfl_tipo_causa     = '" + entity.getTipoCausa() + "', \n"
                    + "       evfl_pafl_flujo     = '" + entity.getSiguiente().getClave().replace("'", "''") + "', \n"
                    + "       evfl_pafl_monto     = '" + (entity.getSiguienteMonto() != null
                    ? entity.getSiguienteMonto().getClave().replace("'", "''")
                    : "") + "', \n"
                    + "       evfl_valida_forzosos = '" + (entity.isValidaForzosos() ? "S" : "N") + "', \n"
                    + "       evfl_tipo_aprobacion    = '" + entity.getTipoAprobacion() + "', \n"
                    + "       evfl_numero_aprobadores = " + entity.getAprobadores() + ", \n"
                    + "       evfl_usuario_modif  = '" + usuario + "', \n"
                    + "       evfl_fecha_modif    = SYSDATE \n"
                    + "WHERE  evfl_clave          = '" + entity.getClave() + "' \n"
                    + "AND    evfl_pafl_origen    = '" + entity.getOrigen().getClave().replace("'", "''") + "' \n"
                    + "AND    evfl_fluj_clave     = '" + entity.getOrigen().getFlujo().getClave().replace("'", "''") + "'";
            conexion = ConexionPool.getInstancia().getConexion();
            sentencia = conexion.prepareStatement(query);
            sentencia.executeUpdate();
            invalidaFlujo = conexion.prepareStatement(
                    invalidarFlujo(entity.getOrigen().getFlujo().getClave().replace("'", "''"),
                    usuario));
            invalidaFlujo.executeUpdate();
        } catch (SQLException ex) {
            throw new DAOException("Error EVDU-SQL " + ex.getMessage());
        } finally {
            try {
                if (sentencia != null) {
                    sentencia.close();
                }
                if (invalidaFlujo != null) {
                    invalidaFlujo.close();
                }
                if (conexion != null) {
                    conexion.close();
                }
            } catch (SQLException ex) {
                throw new DAOException("Error EVDU-SQL " + ex.getMessage());
            }
        }
    }

    protected List<Evento> select() throws DAOException {
        Connection conexion = null;
        PreparedStatement sentencia = null;
        ResultSet resultado = null;
        List<Evento> resultados = null;
        try {
            conexion = ConexionPool.getInstancia().getConexion();
            sentencia = conexion.prepareStatement(query);
            resultado = sentencia.executeQuery();
            resultados = new ArrayList<Evento>();
            while (resultado.next()) {
                Evento evento = new Evento();
                evento.setOrigen(Pasos.instancia().porClave(resultado.getString("clave_flujo"), resultado.getString("clave_paso")));
                evento.setClave(resultado.getString("clave"));
                evento.setDescripcionCorta(resultado.getString("descripcion_corta") == null
                        ? ""
                        : resultado.getString("descripcion_corta"));
                evento.setDescripcion(resultado.getString("descripcion"));
                evento.setSiguiente(Pasos.instancia().porClave(resultado.getString("clave_flujo"), resultado.getString("sig_paso")));
                if (!(resultado.getString("sig_paso_monto") == null || resultado.getString("sig_paso_monto").equals(""))) {
                    evento.setSiguienteMonto(Pasos.instancia().porClave(resultado.getString("clave_flujo"), resultado.getString("sig_paso_monto")));
                }

                evento.setTipoAprobacion(resultado.getString("tipo_aprobacion") == null
                        ? ""
                        : resultado.getString("tipo_aprobacion"));
                evento.setAprobadores(resultado.getInt("aprobadores"));

                evento.setCausable(resultado.getString("causable").equalsIgnoreCase("S"));
                evento.setTipoCausa(resultado.getString("tipo_causa") == null
                        ? ""
                        : resultado.getString("tipo_causa"));
                evento.setValidaForzosos(resultado.getString("forzosos").equalsIgnoreCase("S"));//
                resultados.add(evento);
            }
        } catch (SQLException ex) {
            throw new DAOException("Error EVDS-SQL " + ex.getMessage());
        } finally {
            try {
                if (resultado != null) {
                    resultado.close();
                }
                if (sentencia != null) {
                    sentencia.close();
                }
                if (conexion != null) {
                    conexion.close();
                }
            } catch (SQLException ex) {
                throw new DAOException("Error EVDS-SQL " + ex.getMessage());
            }
        }
        return resultados;
    }

    public List<Evento> selectAll() throws DAOException {
        query = "SELECT evfl_fluj_clave         AS clave_flujo, \n"
                + "       evfl_pafl_origen        AS clave_paso, \n"
                + "       evfl_clave              AS clave, \n"
                + "       evfl_descripcion        AS descripcion, \n"
                + "       evfl_desc_corta         AS descripcion_corta, \n"
                + "       evfl_tipo_aprobacion    AS tipo_aprobacion, \n"
                + "       evfl_numero_aprobadores AS aprobadores, \n"
                + "       evfl_requiere_causa     AS causable, \n"
                + "       evfl_tipo_causa         AS tipo_causa, \n"
                + "       evfl_valida_forzosos    AS forzosos, \n"
                + "       evfl_pafl_flujo         AS sig_paso, \n"
                + "       evfl_pafl_monto         AS sig_paso_monto \n"
                + "FROM   sil_eventos_flujo "
                + "ORDER  BY 1";
        return select();
    }

    public List<Evento> selectWhere(String condition) throws DAOException {
        query = "SELECT evfl_fluj_clave     AS clave_flujo, \n"
                + "       evfl_pafl_origen    AS clave_paso, \n"
                + "       evfl_clave          AS clave, \n"
                + "       evfl_descripcion    AS descripcion, \n"
                + "       evfl_desc_corta     AS descripcion_corta, \n"
                + "       evfl_tipo_aprobacion    AS tipo_aprobacion, \n"
                + "       evfl_numero_aprobadores AS aprobadores, \n"
                + "       evfl_requiere_causa AS causable, \n"
                + "       evfl_tipo_causa     AS tipo_causa, \n"
                + "       evfl_valida_forzosos   AS forzosos, \n"
                + "       evfl_pafl_flujo     AS sig_paso, \n"
                + "       evfl_pafl_monto     AS sig_paso_monto \n"
                + "FROM   sil_eventos_flujo \n"
                + "WHERE  " + condition
                + " ORDER BY 1";
        return select();
    }

    public List<Evento> selectPrimerEvento(String claveFlujo) throws DAOException {
        query = "SELECT evfl_fluj_clave     AS clave_flujo, \n"
                + "       evfl_pafl_origen    AS clave_paso, \n"
                + "       evfl_clave          AS clave, \n"
                + "       evfl_descripcion    AS descripcion, \n"
                + "       evfl_desc_corta     AS descripcion_corta, \n"
                + "       evfl_tipo_aprobacion    AS tipo_aprobacion, \n"
                + "       evfl_numero_aprobadores AS aprobadores, \n"
                + "       evfl_requiere_causa AS causable, \n"
                + "       evfl_tipo_causa     AS tipo_causa, \n"
                + "       evfl_valida_forzosos   AS forzosos, \n"
                + "       evfl_pafl_flujo     AS sig_paso, \n"
                + "       evfl_pafl_monto     AS sig_paso_monto \n"
                + "FROM   sil_flujos, \n"
                + "       sil_pasos_flujo, \n"
                + "       sil_eventos_flujo \n"
                + "WHERE  pafl_tipo_paso   = 'I' \n"
                + "AND    fluj_clave       = '" + claveFlujo + "' \n"
                + "AND    evfl_pafl_origen = pafl_clave \n"
                + "AND    evfl_fluj_clave  = fluj_clave \n"
                + "AND    pafl_fluj_clave  = fluj_clave";
        return select();
    }

    private String invalidarFlujo(String clave, String usuario) {
        return "UPDATE sil_flujos \n"
                + "SET    fluj_usuario_modif = '" + usuario + "', \n"
                + "       fluj_estatus       = 'N', \n"
                + "       fluj_fecha_modif   = SYSDATE \n"
                + "WHERE  fluj_clave         = '" + clave + "'";
    }
}
